#include "stm32f10x.h"   //包含需要的头文件
#include "sys.h"
#include "control.h"     //包含需要的头文件
#include "stdlib.h" 
#include "delay.h"       //包含需要的头文件
#include "usart1.h"      //包含需要的头文件
#include "usart2.h"      //包含需要的头文件
#include "timer2.h"      //包含需要的头文件
#include "wifi.h"	     //包含需要的头文件
#include "led.h"	     //包含需要的头文件 LED                                                  
#include "mqtt.h"        //包含需要的头文件
#include "ds18b20.h"
#include "menu.h"
#include <stdio.h>
#include "oled.h"
#include "buzzer.h"
#include "TM1638.h"
#include "l298n.h"
#include "pid.h" 
#include <stdlib.h>
#include "lcd_init.h"
#include "lcd.h"
#include "pic.h"
u8 speed=100,speed2=100;
float A=OFF,num2;
short  temperature;
unsigned int TEMP;						//储存的实际实时温度
unsigned int SETTEMP;					//储存的实际设置温度*10
unsigned int PWM=2500;
u8 flag100ms=0;
extern int fanc;
extern u8 mode;
extern u8 flag1min;
int keyflag=0;								//本地开关变化标志位
int FANPWM2;
int lih=OFF,lih2=OFF,lih3=OFF,lih4=OFF,lih5=OFF,lih6=OFF;//LED状态
extern unsigned int  settemp;//储存的实际设置温度
unsigned char flag500ms=0;

char *cmdLED_On = "LEDON";      //LED打开
char *cmdLED_Off = "LEDOFF";    //LED关闭

char *cmdDHT11_On = "DHTON";    //温湿度数据传输打开
char *cmdDHT11_Off = "DHTOFF";  //温湿度数据传输关闭
char *dataPtr;
char *ledFlag = "LEDOFF";       //LED状态
int  FanFlag=0;								//风扇状态
extern int airFlag,displayl;
char *dhtFlag = "DHTOFF";		        //温湿度数据传输状态

int main(void) 
{	
	Delay_Init();          //延时功能初始化
//  SysTick_Config(72000);	
	Usart1_Init(115200);     //串口1功能初始化，波特率9600
	Usart2_Init(115200);   //串口2功能初始化，波特率115200	
	TIM4_Init(500,7200);   //TIM4初始化，定时时间 500*7200*1000/72000000 = 50ms
	LED_Init();			   //LED初始化
	DS18B20_Init();
	WiFi_ResetIO_Init();   //初始化WiFi的复位IO
	IoT_Parameter_Init();  //初始化云IoT平台MQTT服务器的参数	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	BUZZER_Init();
	TM1638_Init(); //TM1638初始化函数
	OLED_Init();	
	Motor_12_init();
	TIM3_Int_Init(10000-1,72-1);
	PID_Init();
	PID_Init2();
  TIM3_IRQHandler();
	LCD_Init();//LCD初始化
	LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
	LCD_Fill(0,205,240,240,LIGHTBLUE);
	LCD_Fill(0,0,240,35,LIGHTBLUE);//指定区域填充颜色
	while(1)
	{		
		loop();
		TEMP=DS18B20_Get_Temp();
		fan_pid();
		flagsend();
		TIM_SetCompare2(TIM3,displayl*2000);
		if(airFlag==ON){
				air_pid();
		}	
		if(airFlag==OFF){
				PWM=0;settemp=0;TIM_SetCompare4(TIM3,PWM);
//				TM1638_Display_LED(7,OFF);
		}			
		tft188();
		// connectFlag=1同服务器建立了连接 
		if(connectFlag == 1) 
		{     
			/*-------------------------------------------------------------*/
			/*                     处理发送缓冲区数据						 */
			/*-------------------------------------------------------------*/
			if(MQTT_TxDataOutPtr != MQTT_TxDataInPtr) //if成立的话，说明发送缓冲区有数据了
			{                
				//3种情况可进入if
				//第1种：0x10 连接报文
				//第2种：0x82 订阅报文，且connectPackFlag置位，表示连接报文成功
				//第3种：subcribePackFlag置位，说明连接和订阅均成功，其他报文可发
				if((MQTT_TxDataOutPtr[2] == 0x10)||((MQTT_TxDataOutPtr[2] == 0x82)&&(connectPackFlag == 1))||(subcribePackFlag == 1)) 
				{    
					if (MQTT_TxDataOutPtr[2] == 0x30) 
					{	
						u1_printf("发送数据:0x%x，单片机数据推送至服务器\r\n", MQTT_TxDataOutPtr[2]);	
						u1_printf("\r\n");
					}
					else 
					{
						u1_printf("发送数据:0x%x\r\n", MQTT_TxDataOutPtr[2]);//串口提示信息
					}
					
					MQTT_TxData(MQTT_TxDataOutPtr);							//发送数据
					MQTT_TxDataOutPtr += TBUFF_UNIT;						//指针下移
					if(MQTT_TxDataOutPtr == MQTT_TxDataEndPtr)				//如果指针到缓冲区尾部了
					{ 
						MQTT_TxDataOutPtr = MQTT_TxDataBuf[0];				//指针归位到缓冲区开头
					}	
				} 				
			}
			/*-------------------------------------------------------------*/
			/*                     处理接收缓冲区数据                      */
			/*-------------------------------------------------------------*/
			if(MQTT_RxDataOutPtr != MQTT_RxDataInPtr) //if成立的话，说明接收缓冲区有数据了	
			{												
				u1_printf("接收到数据:");
				/*-----------------------------------------------------*/
				/*                    处理CONNACK报文                  */
				/*-----------------------------------------------------*/				
				//if判断，如果第一个字节是0x20，表示收到的是CONNACK报文
				//接着我们要判断第4个字节，看看CONNECT报文是否成功
				if(MQTT_RxDataOutPtr[2] == 0x20)
				{             			
					switch(MQTT_RxDataOutPtr[5])
					{					   
						case 0x00 : u1_printf("CONNECT报文成功\r\n");							//串口输出信息	
										connectPackFlag = 1;									//CONNECT报文成功，订阅报文可发
									break;														//跳出分支case 0x00                                              
						case 0x01 : u1_printf("连接已拒绝，不支持的协议版本，准备重启\r\n");    //串口输出信息
									connectFlag = 0;											//connectFlag置零，重启连接
									break;														//跳出分支case 0x01   
						case 0x02 : u1_printf("连接已拒绝，不合格的客户端标识符，准备重启\r\n");//串口输出信息
									connectFlag = 0;                                            //connectFlag置零，重启连接
									break; 														//跳出分支case 0x02 
						case 0x03 : u1_printf("连接已拒绝，服务端不可用，准备重启\r\n");	    //串口输出信息
									connectFlag = 0;											//connectFlag置零，重启连接
									break;														//跳出分支case 0x03
						case 0x04 : u1_printf("连接已拒绝，无效的用户名或密码，准备重启\r\n");	//串口输出信息
									connectFlag = 0;											//connectFlag置零，重启连接						
									break;														//跳出分支case 0x04
						case 0x05 : u1_printf("连接已拒绝，未授权，准备重启\r\n");				//串口输出信息
									connectFlag = 0;											//connectFlag置零，重启连接						
									break;														//跳出分支case 0x05 		
						default   : u1_printf("连接已拒绝，未知状态，准备重启\r\n");		    //串口输出信息 
									connectFlag = 0;											//connectFlag置零，重启连接					
									break;														//跳出分支case default 								
					}				
			    }			
				//if判断，第一个字节是0x90，表示收到的是SUBACK报文
				//接着我们要判断订阅回复，看看是不是成功
				else if(MQTT_RxDataOutPtr[2] == 0x90)
				{ 
					switch(MQTT_RxDataOutPtr[6])
					{					
						case 0x00 :
						case 0x01 : 
									u1_printf("订阅成功\r\n");			//串口输出信息
//									OLED_Showall(95,1,"con",16,1);
									subcribePackFlag = 1;				//subcribePackFlag置1，表示订阅报文成功，其他报文可发送
									pingFlag = 0;						//pingFlag清零
									TIM1_ENABLE_30S();					//启动30s的PING定时器	
									Send_Data();
									TIM2_ENABLE_10S();
									break;								//跳出分支                                             
						default: 
									u1_printf("订阅失败，准备重启\r\n");//串口输出信息 
									connectFlag = 0;					//connectFlag置零，重启连接
									break;								//跳出分支 								
						}					
			    }
				//if判断，第一个字节是0xD0，表示收到的是PINGRESP报文
				else if(MQTT_RxDataOutPtr[2] == 0xD0)
				{ 
					u1_printf("PING报文回复\r\n");                      //串口输出信息 
					if(pingFlag == 1)
					{                   						        //如果pingFlag=1，表示第一次发送
						 pingFlag = 0;    				       			//要清除pingFlag标志
					}
					else if(pingFlag > 1)	
					{ 				 									//如果pingFlag>1，表示是多次发送了，而且是2s间隔的快速发送
						pingFlag = 0;     				      			//要清除pingFlag标志
						TIM1_ENABLE_30S(); 				      			//PING定时器重回30s的时间
					}				
				}	
				//if判断，如果第一个字节是0x30，表示收到的是服务器发来的推送数据
				//我们要提取控制命令
				else if((MQTT_RxDataOutPtr[2] == 0x30))
			    { 
					u1_printf("服务器等级0推送\r\n"); 		   	//串口输出信息 
					MQTT_DealPushdata_Qs0(MQTT_RxDataOutPtr);   //处理等级0推送数据
				}									
				MQTT_RxDataOutPtr += RBUFF_UNIT;                //指针下移
				if(MQTT_RxDataOutPtr == MQTT_RxDataEndPtr)      //如果指针到缓冲区尾部了
				{
					MQTT_RxDataOutPtr = MQTT_RxDataBuf[0];      //指针归位到缓冲区开头              
				}		          
			}//处理接收缓冲区数据的else if分支结尾
						
			/*---------------------------------------------------------------------------------------------------------------------*/
			/*                    							 处理命令缓冲区数据                   		          			         */
			/*---------------------------------------------------------------------------------------------------------------------*/
			if(MQTT_CMDOutPtr != MQTT_CMDInPtr)							  //if成立的话，说明命令缓冲区有数据了	
			{                             		       
				u1_printf("命令:%s\r\n",&MQTT_CMDOutPtr[2]);              //串口输出信息
				
				dataPtr = strchr(&MQTT_CMDOutPtr[2], ':');	//搜索':'
				
				
				if(!memcmp(&MQTT_CMDOutPtr[2],cmdLED_On,strlen(cmdLED_On)))//判断指令，如果是CMD1 
				{                                            
					ledFlag = "LEDON";  								             
					LED_On();									  		   //LED开启
				}
				else if(!memcmp(&MQTT_CMDOutPtr[2],cmdLED_Off,strlen(cmdLED_Off))) //判断指令，如果是CMD11
				{ 
					ledFlag = "LEDOFF";                                              
					LED_Off(); 								                //LED关闭
				}
				else if(!memcmp(&MQTT_CMDOutPtr[2],cmdDHT11_On,strlen(cmdDHT11_On)))//判断指令，如果是CMD3
				{      
					dhtFlag ="DHTON";                 //dataFlag置1，表示处于采集状态了
					TIM2_ENABLE_10S();           //定时器2，,10s间隔采集温湿度   
				}
				else if(!memcmp(&MQTT_CMDOutPtr[2],cmdDHT11_Off,strlen(cmdDHT11_Off)))//判断指令，如果是CMD3
				{     
					dhtFlag ="DHTOFF";                 //dataFlag置0，表示处于停止状态了
					TIM_Cmd(TIM2,DISABLE);		 //判断2路开关状态和采集状态，并发布给服务器
				}
				else if(!memcmp(&MQTT_CMDOutPtr[2],"add",3))//判断指令，如果是CMD1 
				{                                            
					settemp++;	
				}		
				else if(!memcmp(&MQTT_CMDOutPtr[2],"sub",3))//判断指令，如果是CMD1 
				{                                            
					settemp--;	
				}					
        			
				else if(dataPtr != NULL) //判断指令，如果是CMD11
				{ 
					int num = 0;
					char numBuf[10];
					numBuf[num] = 0;
						dataPtr++;
				while(*dataPtr >= '0' && *dataPtr <= '9')		//判断是否是下发的命令控制数据
				{
					numBuf[num++] =  *dataPtr++;
				}
				numBuf[num] = 0;
				
				num = atoi((const char *)numBuf);				//转为数值形式
				
				if(strstr(&MQTT_CMDOutPtr[2], "LED1"))				//搜索"LED1"
				{
					lih=num;
				}                                           
				else if(strstr(&MQTT_CMDOutPtr[2], "fan"))				//搜索"FAN"
				{
					if(num >= 0 && num <= 4) 
					{fanc=num;}
				} 	
				else if(strstr(&MQTT_CMDOutPtr[2], "LED2"))				//搜索"LED2"
				{
					if(num >= 0 && num <= 1) 
					lih2=num;		
				} 
				else if(strstr(&MQTT_CMDOutPtr[2], "FanFlag"))				//搜索"FanFlag"
				{
					if(num >= 0 && num <= 4) 
						fanc=num;			
				} 
				else if(strstr(&MQTT_CMDOutPtr[2], "airFlag"))				//搜索"FanFlag"
				{
					if(num >= 0 && num <= 1) 
						airFlag=num;
					if(airFlag==1&&mode==1) 
					{settemp=26;	}
					if(airFlag==1&&mode==0) 
					{settemp=40;	}
				} 
				else if(strstr(&MQTT_CMDOutPtr[2], "settemp"))				//搜索"settemp"
				{
					if(num >= 16 && num <= 40) 
						settemp=num;			
				} 
				else if(strstr(&MQTT_CMDOutPtr[2], "mode"))				//搜索"FanFlag"
				{
					if(num >= 0 && num <= 1) 
						mode=num;		
						if(airFlag==1&&mode==1) 
					{settemp=26;	}
					if(airFlag==1&&mode==0) 
					{settemp=40;	}
				} 
				
				}				
				//不做处理，后面会发送状态
				else u1_printf("未知指令\r\n");				//串口输出信息	
			
				MQTT_CMDOutPtr += CBUFF_UNIT;				//指针下移
				if(MQTT_CMDOutPtr == MQTT_CMDEndPtr)	    //如果指针到缓冲区尾部了
				MQTT_CMDOutPtr = MQTT_CMDBuf[0];			//指针归位到缓冲区开头	

				OLED_Clear();//刷屏
				keyflag=!keyflag;//发送控制数据
				//处理命令缓冲区数据的else if分支结尾					
			}	//connectFlag=1的if分支的结尾
		}
	/*--------------------------------------------------------------------*/
	/*      connectFlag=0同服务器断开了连接,我们要重启连接服务器            */
	/*--------------------------------------------------------------------*/
		else
		{ 
			u1_printf("需要连接服务器\r\n");               //串口输出信息
			TIM_Cmd(TIM4, DISABLE);                        //关闭TIM4 
			TIM_Cmd(TIM1, DISABLE);                        //关闭TIM1  
			WiFi_RxCounter = 0;                            //WiFi接收数据量变量清零                        
			memset(WiFi_RX_BUF, 0, WiFi_RXBUFF_SIZE);      //清空WiFi接收缓冲区 
			if(WiFi_Connect_IoTServer() == 0)			   //如果WiFi连接云服务器函数返回0，表示正确，进入if
			{   			     
				u1_printf("建立TCP连接成功\r\n");          //串口输出信息
				connectFlag = 1;                           //connectFlag置1，表示连接成功	
				WiFi_RxCounter = 0;                        //WiFi接收数据量变量清零                        
				memset(WiFi_RX_BUF, 0, WiFi_RXBUFF_SIZE);  //清空WiFi接收缓冲区 
				MQTT_Buff_Init();                          //初始化发送缓冲区                    
			}				
		}
	}
}

void air_pid()//空调pid
{

					if(mode==1){cold();}
					else if(mode==0){hot();}
					SETTEMP=settemp*10;
					TIM_SetCompare4(TIM3,PWM);
		 if(flag100ms)										//每100ms更新一次实时温度
		{
			flag100ms=0;
			flag500ms++;
			if(flag500ms==2)                //500ms测量一次pid温度
			{
				flag500ms=0;
				if(mode==1){PWM=PID_realize2();}//制冷
		    else if(mode==0){PWM=PID_realize();}//制热
				TIM_SetCompare4(TIM3,PWM);
			}
		}
		TIM_SetCompare4(TIM3,PWM);
	

}

void fan_pid()//风扇pwm调速
{
	TM1638_Display_LED(0,lih);TM1638_Display_LED(1,lih2);
	TM1638_Display_LED(2,lih3);TM1638_Display_LED(3,lih4);
	TM1638_Display_LED(4,lih5);TM1638_Display_LED(5,lih6);
	FanFlag=fanc;

	 fan();
   switch(fanc)
				{
					case 0:FANPWM2=0;
							break;
					case 1:FANPWM2=2500;
							break;
					case 2:FANPWM2=5000;
							break;
					case 3:FANPWM2=7500;
							break;
					case 4:FANPWM2=9999;
              break;
					default:break;
				}
   TIM_SetCompare3(TIM3,FANPWM2);
}

void tft188()
{		
//			LCD_ShowIntNum(220,5,subcribePackFlag,1,BLACK,WHITE,24);
			LCD_ShowChinese(210,5,"●",subcribePackFlag==0?GRAY:GREEN,LIGHTBLUE,24,0);
			LCD_ShowString(150,7,"onenet:",BLACK,LIGHTBLUE,16,1);
			LCD_ShowPicture(200,35,39,65,gImage_111);

			LCD_ShowPicture(5,85,32,32,gImage_13);
		  LCD_ShowString(40,92,":",BLACK,WHITE,24,0);
	    LCD_ShowChinese(60,92,lih2==0?"关":"开",BLACK,WHITE,24,0);
			
			LCD_ShowPicture(125,85,32,32,gImage_18);
		  LCD_ShowString(160,92,":",BLACK,WHITE,24,0);
	    LCD_ShowChinese(178,92,lih==0?"关":"开",BLACK,WHITE,24,0);
	
			LCD_ShowPicture(200,35,39,65,gImage_112);
	
			LCD_ShowPicture(5,45,32,32,gImage_14);
		  LCD_ShowString(40,52,":",BLACK,WHITE,24,1);
			LCD_ShowIntNum(60,52,(DS18B20_Get_Temp()/10%100),2,BLACK,WHITE,24);
			LCD_ShowChar(84,52,'.',BLACK,WHITE,24,1);
			LCD_ShowIntNum(95,52,(DS18B20_Get_Temp()/1%10),1,BLACK,WHITE,24);
			LCD_ShowChinese(113,52,"℃",BLACK,WHITE,24,0);
			
			LCD_ShowPicture(5,125,32,32,gImage_15);
		  LCD_ShowString(40,132,":",BLACK,WHITE,24,0);
	    LCD_ShowChinese(60,132,airFlag==0?"关":"开",BLACK,WHITE,24,0);
			
			LCD_ShowPicture(200,35,39,65,gImage_113);
			
			LCD_ShowPicture(124,125,33,32,gImage_12);
		  LCD_ShowString(160,132,":",BLACK,WHITE,24,0);
		  LCD_ShowIntNum(180,132,FanFlag,1,BLACK,WHITE,24);
			LCD_ShowChinese(192,132,"档",BLACK,WHITE,24,0);
			
			LCD_ShowPicture(5,165,32,32,gImage_16);
		  LCD_ShowString(40,172,":",BLACK,WHITE,24,0);
	    LCD_ShowChinese(60,172,mode==1?"制冷":"制热",BLACK,WHITE,24,0);
	
			LCD_ShowPicture(200,35,39,65,gImage_114);	
			
			LCD_ShowPicture(125,165,32,32,gImage_17);
		  LCD_ShowString(160,172,":",BLACK,WHITE,24,0);
	    LCD_ShowIntNum(180,172,settemp,2,BLACK,WHITE,24);
			LCD_ShowChinese(204,172,"℃",BLACK,WHITE,24,0);
			

			 if(TM1638_ReadKey()==6) 
				{	
					DelayMs(13);
					if(TM1638_ReadKey()==6)		
					LCD_Init();//LCD初始化
					LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
					LCD_Fill(0,0,240,35,LIGHTBLUE);
					LCD_Fill(0,205,240,240,LIGHTBLUE);
				} 

}
void flagsend()//判断变化上传一回数据
{
	if(keyflag==1)
	{
			Send_Data();
			keyflag=0;
	}
	
}
